#pragma once

#ifndef __COORDINATE_H__
#define __COORDINATE_H__

// ---------------------------------------------------------------------------------------------------------------------------------------------------------
// > 地平坐标系(Horizontal system)
//   -> 高度角(Alt/Altitude)
//         - 描述：物体在观察者地平线上方的角距离;
//         - 符号：h [ 太阳高度角：θ(theta)],
//         - 起点：地平线
//         - 单位：度;
//         - 范围：[-90°,+90°]从天顶的+90°到天底的-90°。        -
//   -> 方位角(Az/(Azimuth angle))
//         - 描述：是从某点的指北方向线起，依顺时针方向到目标方向线之间的水平夹角;
//         - 符号：α(alpha),
//         - 起点：真北（指向地理北极的方向）
//         - 单位：度、密位 （方位角用a表，磁方位角用Am表示）;
//         - 范围：[0°, 360°] 北点为0°，东点为90°，南点为180°，西点为270°。
// ---------------------------------------------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------------------------------------------
// > 赤道坐标系统(Equatorial system)
//   -> 赤经(RA/RightAscension)
//         - 描述：天球两极并与天赤道垂直;
//         - 符号：α(alpha),
//         - 起点：春分点(从春分点起沿天赤道向东计算)
//         - 单位： {时、分、秒}/{h、m、s};
//         - 范围：[0H, 24H],自春分点起，按与天球周日视运动相反的方向量度，从0h到24h;
//   -> 赤纬(Dec/Declination)
//         - 描述：从天赤道沿着天体的时圈至天体的角度称为该天体的赤纬;
//         - 符号：δ(delta),
//         - 起点：天赤道
//         - 单位：度，更小的单位是“角分”和“角秒”
//         - 范围：[-90°, +90°],天赤道为0度，天北半球的赤纬度数为正数，天南半球的赤纬的度数为负数。天北极为+90°，天南极为-90°(向北为正，向南为负)
//                 日赤纬范围[-23°27'～+23°27']，
//                 月赤纬范围[-28°36'～+28°36'],
// ---------------------------------------------------------------------------------------------------------------------------------------------------------
// ---------------------------------------------------------------------------------------------------------------------------------------------------------
// > 黄道坐标系统(Ecliptic system)
//   -> 黄经(EL/EclipticLongitude)
//         - 描述：用来确定天体在天球上位置的一个坐标值;
//         - 符号：λ(lamdba),
//         - 起点：春分点
//         - 单位：度，更小的单位是“角分”和“角秒”
//         - 范围：[0°，360°] 由西向东量度
//   -> 黄纬(Dec/EclipticLatitude)
//         - 描述：从天赤道沿着天体的时圈至天体的角度称为该天体的赤纬;
//         - 符号：β(bata),
//         - 起点：黄经圈
//         - 单位：度，更小的单位是“角分”和“角秒”
//         - 范围：[-90°, +90°]北黄极为+90°，南南极为-90°(向北为正，向南为负)
// ---------------------------------------------------------------------------------------------------------------------------------------------------------

class Coordinate2D
{
public:
    double X{0}; // Alpha,Lambda; RA(赤经);
    double Y{0}; // Delta;       Dec(赤纬);
public:
    double operator[](size_t index) const
    {
        switch (index)
        {
        case 0 :
            return this->X;
        case 1 :
            return this->Y;
        default :
            break;
        }
        return 0;
    }

    Coordinate2D RadiansToDegrees();

    Coordinate2D operator+(const Coordinate2D *other) const { return {this->X + other->X, this->Y + other->Y}; }
};

class Coordinate3D
{
public:
    double X{0}; // r, Alpha,Lambda; RA(赤经);
    double Y{0}; // θ,Delta;        Dec(赤纬);
    double Z{0}; // φ,

public:
    Coordinate3D RadiansToDegrees() noexcept;

    void EclipticToEquatorial(const double Epsilon) noexcept;

public:
    double operator[](size_t index) const
    {
        switch (index)
        {
        case 0 :
            return this->X;
        case 1 :
            return this->Y;
        case 2 :
            return this->Z;
        default :
            break;
        }
        return 0;
    }
    Coordinate3D &operator=(const Coordinate2D &coordinate2D)
    {
        this->X = coordinate2D.X;
        this->Y = coordinate2D.Y;
        return *this;
    }
    Coordinate3D &operator=(const Coordinate3D &coordinate3D)
    {
        this->X = coordinate3D.X;
        this->Y = coordinate3D.Y;
        this->Z = coordinate3D.Z;
        return *this;
    }
    Coordinate3D  operator+(const Coordinate3D &other) { return {this->X + other.X, this->Y + other.Y, this->Z + other.Z}; }
    Coordinate3D  operator-(const Coordinate3D &other) { return {this->X - other.X, this->Y - other.Y, this->Z - other.Z}; }
    Coordinate3D &operator-=(const Coordinate3D &other)
    {
        this->X -= other.X;
        this->Y -= other.Y;
        this->Z -= other.Z;

        return *this;
    }
    Coordinate2D operator=(Coordinate3D &coordinate2D) { return {coordinate2D.X, coordinate2D.Y}; }
};

#endif